package com.mf.service.impl.basic;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.entity.dto.basic.DtoDic;
import com.mf.entity.dto.basic.DtoRole;
import com.mf.entity.req.basic.reqPublic.ReqPublicIds;
import com.mf.entity.req.basic.search.SearchReqDic;
import com.mf.mapper.basic.MapperDic;
import com.mf.service.basic.ServiceDic;
import com.mf.service.basic.ServiceRole;
import com.mf.utils.UtilSql;
import com.mf.utils.tree.UtilTree;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class ImplServiceDic extends ServiceImpl<MapperDic, DtoDic> implements ServiceDic {

    @Resource
    private ServiceRole serviceRole;

    /**
     * 参数查询条件
     */
    @Override
    public LambdaQueryWrapper<DtoDic> fillParams(SearchReqDic params) {
        LambdaQueryWrapper<DtoDic> wr = loadQw();


        if (StringUtils.isNotBlank(params.getKey())) {
            wr.and(w -> {
                w.like(DtoDic::getDicCode, params.getKey())
                        .or()
                        .like(DtoDic::getDicName, params.getKey())
                        .or()
                        .like(DtoDic::getDicValue, params.getKey())
                        .or()
                        .apply(UtilSql.sqlJsonKey(DtoDic::getRoleList), UtilSql.sqlJsonValue(params.getKey()));
            });
        }
        wr.eq(ObjectUtils.isNotEmpty(params.getStatus()), DtoDic::getStatus, params.getStatus()).orderByDesc(DtoDic::getSort).orderByDesc(DtoDic::getId);

        return wr;
    }


    /**
     * 根据父级id查询字典数据内容
     */
    @Override
    public Map<Integer, List<DtoDic>> listByPid(ReqPublicIds<Integer> pIds) {
        LambdaQueryWrapper<DtoDic> wrapper = loadQw();
        wrapper.in(DtoDic::getPid, pIds.getIds());
        List<DtoDic> list = list(wrapper);
        return list.stream().collect(Collectors.groupingBy(DtoDic::getPid));
    }

    /**
     * 列表查询树结构
     */
    @Override
    public List<DtoDic> listTree(SearchReqDic searchReqDic) {
        List<DtoDic> dtoDic = UtilTree.filterTree(list(), findListByParams(searchReqDic));
        List<Integer> roleList = StpUtil.getRoleList().stream().map(Integer::parseInt).toList();
        List<DtoRole> dtoRoles = serviceRole.list();
        return filterTreeByRole(dtoDic, roleList, dtoRoles);
    }

    /**
     * 通过角色过滤返回的树结构数据
     */
    public List<DtoDic> filterTreeByRole(List<DtoDic> list, List<Integer> roleList, List<DtoRole> dtoRoles) {
        return list.stream()
                .map(node -> filterNode(node, roleList, dtoRoles))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 递归过滤树结构数据
     */
    private DtoDic filterNode(DtoDic node, List<Integer> roleList, List<DtoRole> dtoRoles) {
        boolean hasRole = ObjectUtils.isNotEmpty(node.getRoleList());
        Set<Integer> roleSet = new HashSet<>(roleList);
        boolean roleMatch = !hasRole || roleSet.stream().anyMatch(node.getRoleList()::contains);

        // 如果当前节点匹配（无角色 或 角色匹配）
        if (roleMatch) {
            node.setRoleNameList(getRoleNameList(node, dtoRoles));
            // 递归处理子节点
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                List<DtoDic> filteredChildren = node.getChildren().stream()
                        .map(child -> {
                            child.setRoleNameList(getRoleNameList(child, dtoRoles));
                            return filterNode(child, roleList, dtoRoles);
                        })
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());

                node.setChildren(filteredChildren);
            }
            return node;
        }

        // 不满足条件返回 null，表示不保留该节点
        return null;
    }

    private static List<String> getRoleNameList(DtoDic node, List<DtoRole> dtoRoles) {
        return dtoRoles.stream().filter(v -> {
            if (node.getRoleList() != null) {
                return node.getRoleList().contains(v.getId());
            } else {
                return false;
            }
        }).map(DtoRole::getRoleName).toList();
    }


    /**
     * 根据id查询子数量
     */
    @Override
    public long countByPid(Integer id) {
        LambdaQueryWrapper<DtoDic> wrapper = loadQw();
        wrapper.eq(DtoDic::getPid, id);
        return count(wrapper);
    }
}